/******************************************************************************
*  A Teaching GA					  Developed by Hal Stringer & Annie Wu, UCF
*  Version 2, January 18, 2004
* 
*  Modified by Lisa Soros, February 2012
*******************************************************************************/

import java.io.*;
import java.util.*;
import java.text.*;
import java.lang.Math;

public class Coefficients extends FitnessFunction{

	double[][] data;

	public Coefficients(double[][] data){
		name = "Coefficients Problem, Add'l Representation";
		this.data = data;
	}

//  COMPUTE A CHROMOSOME'S RAW FITNESS *************************************

	public void doRawFitness(Chromo xx)
	{
      HexChromo x = (HexChromo)xx;
	// Chromo X should have length up to 45 bits
	// (2's complement; 9 bits for each coefficient)
		
		// Convert 2's complement to decimal
		long aDec, bDec, cDec, dDec, eDec;
		aDec = twosComp(x.chromo.substring(0, 9));
		bDec = twosComp(x.chromo.substring(9, 18));
		cDec = twosComp(x.chromo.substring(18, 27));
		dDec = twosComp(x.chromo.substring(27, 36));
		eDec = twosComp(x.chromo.substring(36, 45));
		
		// Compare equation results to desired results
		// Difference from y gives fitness
		double results;
		double xValue, yValue;
		x.rawFitness = 0;
		for(int i = 0; i<data.length; i++)
		{
			xValue = data[i][0];
			yValue = data[i][1];
			results = (aDec * xValue * xValue) + (bDec * xValue) + cDec + (dDec * Math.sin(xValue)) + (eDec * Math.cos(xValue));
			x.rawFitness += (Double)Math.abs(yValue - results);
		}
	}
		
	// Utility function used to translate 2's complement hex into decimal
	// Not entirely mine: created using some inspiration from StackOverflow	
	public static long twosComp(String str) 
	{
		long num = Long.valueOf(str, 16);
      if (((1L<<35)&num) != 0)
         num = num-(1L<<36);
      return num;
   }
	

//  PRINT OUT AN INDIVIDUAL GENE TO THE SUMMARY FILE *********************************

	public void doPrintGenes(Chromo xx, FileWriter output) throws java.io.IOException
	{
      BinaryChromo x = (BinaryChromo)xx;
		output.write("RawFitness: " + x.rawFitness + "\n");
		
		// Convert 2's complement to decimal
		long aDec, bDec, cDec, dDec, eDec;
		aDec = twosComp(x.chromo.substring(0, 9));
		bDec = twosComp(x.chromo.substring(9, 18));
		cDec = twosComp(x.chromo.substring(18, 27));
		dDec = twosComp(x.chromo.substring(27, 36));
		eDec = twosComp(x.chromo.substring(36, 45));
		
		output.write("A: " + aDec + "\n");
		output.write("B: " + bDec + "\n");
		output.write("C: " + cDec + "\n");
		output.write("D: " + dDec + "\n");
		output.write("E: " + eDec + "\n");
		
		output.write("\n\n");
		return;
	}
}

